import pandas as pd
from sklearn.model_selection import train_test_split
from sklearn.linear_model import LinearRegression
from sklearn.metrics import mean_squared_error, r2_score, mean_absolute_error
import numpy as np
import matplotlib.pyplot as plt
import time  # 导入时间模块

# 设置图片清晰度
plt.rcParams['figure.dpi'] = 300

# 设置 matplotlib 支持中文，将字体更换为 SimHei
plt.rcParams['font.sans-serif'] = ['SimHei']
plt.rcParams['axes.unicode_minus'] = False

# 读取 Excel 文件
excel_file = pd.ExcelFile(r'D:\xwechat_files\wxid_zckpz7oz0who22_41a5\msg\file\2025-08\9个数据集数据\7-鲍鱼年龄.xlsx')

# 获取指定工作表中的数据
df = excel_file.parse('Sheet1')

# 对性别进行独热编码
df = pd.get_dummies(df, columns=['性别'], drop_first=True)

# 准备特征和目标变量
X = df.drop('年龄', axis=1)
y = df['年龄']

# 划分训练集和测试集（预测数据），80% 为训练集，20% 为测试集
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)

# 创建线性回归模型
model = LinearRegression()

# 记录训练开始时间
train_start_time = time.perf_counter()  # 使用高精度计时器[1](@ref)

# 训练模型
model.fit(X_train, y_train)

# 记录训练结束时间并计算训练耗时
train_end_time = time.perf_counter()
training_time_ms = (train_end_time - train_start_time) * 1000  # 转换为毫秒

# 记录预测开始时间
predict_start_time = time.perf_counter()

# 在测试集（预测数据）上进行预测
y_pred = model.predict(X_test)

# 记录预测结束时间并计算预测耗时
predict_end_time = time.perf_counter()
total_prediction_time_ms = (predict_end_time - predict_start_time) * 1000  # 总预测时间(ms)

# 计算每个测试样本的平均预测时间
avg_prediction_time_per_sample_ms = total_prediction_time_ms / len(X_test)

# 计算多种性能指标
mse = mean_squared_error(y_test, y_pred)
r2 = r2_score(y_test, y_pred)
mae = mean_absolute_error(y_test, y_pred)
rmse = np.sqrt(mse)

print(f'均方误差 (MSE): {mse}')
print(f'决定系数 (R2): {r2}')
print(f'平均绝对误差 (MAE): {mae}')
print(f'均方根误差 (RMSE): {rmse}')

# 输出训练和预测时间信息[2,5](@ref)
print(f"\n模型训练时间: {training_time_ms:.4f} ms")
print(f"测试集总预测时间: {total_prediction_time_ms:.4f} ms")
print(f"每个测试样本平均预测时间: {avg_prediction_time_per_sample_ms:.4f} ms")

# 打印模型系数和截距
coefficients = model.coef_
intercept = model.intercept_
feature_names = X.columns

print("\n模型系数:")
for feature, coef in zip(feature_names, coefficients):
    print(f"{feature}: {coef}")
print(f"截距: {intercept}")

# 绘制预测值和真实值的对比图
plt.figure(figsize=(10, 6))
plt.scatter(y_test, y_pred)
plt.plot([y_test.min(), y_test.max()], [y_test.min(), y_test.max()], 'k--', lw=2)
plt.xlabel('真实年龄')
plt.ylabel('预测年龄')
plt.title('线性回归预测结果与真实结果对比')
plt.savefig('prediction_vs_true.png')

# 计算残差
residuals = y_test - y_pred

# 绘制残差图
plt.figure(figsize=(10, 6))
plt.scatter(y_pred, residuals)
plt.axhline(y=0, color='r', linestyle='--')
plt.xlabel('预测值')
plt.ylabel('残差')
plt.title('残差图')
plt.savefig('residual_plot.png')